import { _decorator, Component, SpriteFrame, Animation } from 'cc';
import State from './State';
import { FSM_PARAMS_TYPE_ENUM } from '../Enums';
import { SubStateMachine } from './SubStateMachine';
const { ccclass, property } = _decorator;


/**
 * @boolean: trigger触发器
 * @number: number型参数
 */
type ParamsValueType = boolean | number

export interface IParamsValue {
  type:FSM_PARAMS_TYPE_ENUM,
  value:ParamsValueType
}
export const getInitParamsTrigger = () => {
  return {
    type: FSM_PARAMS_TYPE_ENUM.TRIGGER,
    value: false
  }
}
export const getInitParamsNumber = () => {
  return {
    type: FSM_PARAMS_TYPE_ENUM.NUMBER,
    value: 0
  }
}

/***
 * 流动图
 * 1.entity的state或者direction改变触发setter (数据)
 * 2.setter里触发fsm的setParams方法 (视图)
 * 3.setParams执行run方法（run方法由子类重写）
 * 4.run方法会更改currentState，然后触发currentState的setter
 * 5-1.如果currentState是子状态机，继续执行他的run方法，run方法又会设置子状态机的currentState，触发子状态run方法
 * 5-2.如果是子状态，run方法就是播放动画
 */

/**
 * 有限状态机 fsm 基类
 */
@ccclass('StateMachine')
export abstract class StateMachine extends Component {
  // 当前状态
  private _currentState: State | SubStateMachine
  // 参数列表
  params: Map<string, IParamsValue> = new Map()
  // 状态列表
  states: Map<string, State | SubStateMachine> = new Map()
  /**
   * fsm内置的这个动画组件
   */
  animationComponent:Animation
  //
  waitingList:Array<Promise<SpriteFrame[]>> = []



  getParams(paramName:string) {
    if(this.params.get(paramName)) {
      return this.params.get(paramName).value
    }
  }
  /**
   * 改变属性值，会执行 run 方法，run里面会对状态机 状态进行切换
   */
  setParams(paramName:string, newValue:ParamsValueType) {
    if(this.params.get(paramName)) {
      this.params.get(paramName).value = newValue
      // 执行方法, 看看改变这个值后，会触发什么
      this.run()
      this.resetTrigger()
    }
  }
  get currentState() {
    return this._currentState
  }
  /**
   * 改变状态机的状态，会
   */
  set currentState(newState:State|SubStateMachine) {
    this._currentState = newState
    this._currentState.run()
  }
  // 清空 trigger
  resetTrigger() {
    for (const [_, pValue] of this.params) {
      if (pValue.type === FSM_PARAMS_TYPE_ENUM.TRIGGER) {
        pValue.value = false
      }
    }
  }
  abstract init() :void
  /**
   * 具体类实现，当 params 值发生变化时，应当如何判断
   */
  abstract run() :void

}
// 森林（大树居民村落、星落湖、）
// 城市（）
// 外星文明遗址、冰原、沙漠、
